package de.haw.gka.a1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.jgrapht.alg.DijkstraShortestPath;
import org.jgrapht.graph.AbstractGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.DefaultWeightedEdge;

import org.jgrapht.traverse.BreadthFirstIterator;


public class AlgoBFS extends AbstractSearchAlgo {

	private ArrayList<Object> theWay = new ArrayList<Object>();
	private ArrayList theShortestWay = new ArrayList();
	private int benoetigteKanten =0;


	private boolean isDefaultEgde = false;
	private boolean isString = false;

	public AlgoBFS(AbstractGraph<?, ?> graph, String start, String end){
		Iterator<?> iterEdge = graph.edgeSet().iterator();
		while(iterEdge.hasNext()){
			Object obj = iterEdge.next();
			if(obj instanceof DefaultEdge) {
				isDefaultEgde = true;
				break;
			}else break;
		}
		Iterator<?> isVertex = graph.vertexSet().iterator();
		while(isVertex.hasNext()){
			Object obj = isVertex.next();
			if(obj instanceof String) {
				isString = true;
				break;
			}else
				break;			
		}
		 if(isDefaultEgde && isString){
			out("String && DefaultEdge Ungewichtet ");
			AbstractGraph<String, DefaultEdge> tgraph = (AbstractGraph<String, DefaultEdge>)graph;
			findWayNormal(tgraph, start, end);
			
		 }else if(isString && !isDefaultEgde){
			 out("String && DefaultWeightedEdge");
			 AbstractGraph<String, DefaultWeightedEdge> tgraph = (AbstractGraph<String, DefaultWeightedEdge>)graph;
			 findWayGewichtet(tgraph, start, end);
			
		 }else{
			 out("knoten && DefaultWeightedEdge");
			 AbstractGraph<Knoten, DefaultWeightedEdge> tgraph = ( AbstractGraph<Knoten, DefaultWeightedEdge>) graph;
			 findWayGewichtetAttr(tgraph, start,end);
		 }
		 
		 
	}
	
	private void out(String str){
		System.out.println(str);
	}

	private void findWayNormal(AbstractGraph<String, DefaultEdge> tgragh, String aStart, String aEnd){
		BreadthFirstIterator<String, DefaultEdge> bfsIter = new BreadthFirstIterator<String, DefaultEdge>( tgragh, aStart);
		DijkstraShortestPath<String, DefaultEdge> dijIter = new DijkstraShortestPath<String, DefaultEdge>( tgragh, aStart, aEnd);
		shortWay(bfsIter,dijIter);
	}
	
	private void findWayGewichtet(AbstractGraph<String, DefaultWeightedEdge> tgraph, String aStart, String aEnd){
		BreadthFirstIterator<String, DefaultWeightedEdge> bfsIter = new BreadthFirstIterator<String, DefaultWeightedEdge>(tgraph, aStart);
		DijkstraShortestPath<String, DefaultWeightedEdge> dijIter = new DijkstraShortestPath<String, DefaultWeightedEdge>(tgraph, aStart,aEnd);
		shortWay(bfsIter,dijIter);
	}
	
	
	
	private Knoten getKnoten(AbstractGraph<Knoten, DefaultWeightedEdge> aGraph, String knotenName){
		Iterator<Knoten> iterVertex =  aGraph.vertexSet().iterator();
		while(iterVertex.hasNext()){
			Knoten a = iterVertex.next();
			if(a.getName().equals(knotenName)) return a;
		}
		return null;
	}

	
	
	private void findWayGewichtetAttr(AbstractGraph<Knoten, DefaultWeightedEdge> tgraph, String start, String end){	
		Knoten Kstart = getKnoten(tgraph, start);
		Knoten Kend = getKnoten(tgraph, end);		
		BreadthFirstIterator<Knoten, DefaultWeightedEdge> bfsIter = new BreadthFirstIterator<Knoten, DefaultWeightedEdge>(tgraph, Kstart);
		DijkstraShortestPath<Knoten, DefaultWeightedEdge> dijIter = new DijkstraShortestPath<Knoten, DefaultWeightedEdge>(tgraph,Kstart,Kend);
		shortWay(bfsIter,dijIter);
	}
	
	private void shortWay(BreadthFirstIterator<?, ?> bfsIter,DijkstraShortestPath<?, ?> dijIter){		
		while(bfsIter.hasNext()){
			Object tmp = bfsIter.next();
			theWay.add(tmp);
		}				
		List strTmp = new ArrayList();
		benoetigteKanten =(int) dijIter.getPathLength();
		strTmp.addAll((Collection<?>) dijIter.getPathEdgeList());

        theShortestWay.addAll(dijIter.getPathEdgeList());
	}
	
	
	
	
	public int getBenoetigteKanten(){
		return benoetigteKanten;
	}
	
	public ArrayList getTheShortestWay(){
		return theShortestWay;
	}
	
	
	public ArrayList<Object> getTheWay(){
		return theWay;
	}
	
	
}
